local skynet = require "skynet"
local msg_center = require "agents.msg_center"
local proto_manager = require "common.proto_manager"
local login_manager = require "agents.login_manager"
local MessageType = require "common.message_type"
local watchdog_proxy = require "agents.watchdog_proxy"
local player_manager = require "agents.player_manager"
local time_manager = require "common.time_manager"
local player_listener = require "agents.player_listener"
local msg_handler_helper = require "agents.msg_handler_helper"
local message_packet = require "common.message_packet"

local function onClientConnected(conf)
    local fd = tonumber(conf.client) or 0
    local gate = conf.gate
    local client = login_manager.getClient(fd)
    if client then
        watchdog_proxy.disconnect(fd)
        skynet.error("client already connected! fd:" .. tostring(fd))
        return
    end
    pcall(skynet.call,gate, "lua", "forward", fd)
    local client = login_manager.addClient(fd)
    client:setAlivetime(time_manager.now())
    skynet.error("client connected:" .. tostring(fd))
end
msg_center.setWatchdogMessageHandler(MessageType.OnClientConnected,onClientConnected)

local function onClientDisconnected(fd)
    local client = login_manager.getClient(fd)
    if client then
        login_manager.removeClient(fd)
        local player = player_manager.getPlayerByFd(fd)
        if player then
            player:onOffline()
            player_listener.onPlayerOffline(player)
            skynet.error("player logout openid:" .. player:getOpenID())
        end
    else
        skynet.error("not find client! fd:" .. tostring(fd))
    end
end
msg_center.setWatchdogMessageHandler(MessageType.OnClientDisconnected,onClientDisconnected)


local function onRecvedClientMsg(fd,id)
    local client = login_manager.getClient(fd)
    if client then
        client:setAlivetime(time_manager.now())
    end
end
msg_center.setRecvMsgFilter(onRecvedClientMsg)

local function checkClientAlive(fd,client)
    local now = time_manager.now()
    if now - client:getAlivetime() > 10 then
        skynet.error("checkClientAlive fd time out! fd:" .. tostring(fd))
        watchdog_proxy.disconnect(fd)
    end
end

local clientAlivetimeTimer = nil
local function startClientAlivetimeTimer()
    function timeout()
        login_manager.foreach(checkClientAlive)
        clientAlivetimeTimer = skynet.timeout(100,timeout)
    end
    clientAlivetimeTimer = skynet.timeout(100,timeout)
end

startClientAlivetimeTimer()


local function onEnterGameReq(fd,id,data)

    local req = msg_handler_helper.parseProtoMessage(fd,"MessageEnterGameReq",data)
    if not req then
        return
    end

    local client = login_manager.getClient(fd)
    if not client then
        watchdog_proxy.disconnect(fd)
        skynet.error("not find client! fd:" .. tostring(fd))
        return
    end

    local resp = {
        result = proto_manager.errcode("ErrorCode_Failed"),
        open_id = req.open_id,
    }

    repeat

        if 0 == string.len(req.open_id or "") then
            break
        end

        local player = player_manager.getPlayerByOpenID(req.open_id)
        if player then
            player_manager.online(player,client)
        else
            player = player_manager.addPlayer(req.open_id,client)
        end

        client:setLogined()

        resp.result = proto_manager.ErrorCode_Successed

        player_listener.onPlayerOnline(player)

        skynet.error("player logined openid:" .. player:getOpenID())

    until true

    client:sendMessage("MessageId_EnterGameResp","MessageEnterGameResp",resp)

end
msg_center.setClientMessageHandler(proto_manager.message_id("MessageId_EnterGameReq"),onEnterGameReq)

local function onRegisterPlayerStateNotify(listener)
    player_listener.addListener(listener)
end
msg_center.setDefaultMessageHandler(MessageType.RegisterPlayerStateNotify,onRegisterPlayerStateNotify)

local function onForward2Client(data)

    local pack = message_packet.packSendBuffer(data.message_id,data.message_type,data.msg)

    for _,open_id in ipairs(data.open_ids or {}) do
        local player = player_manager.getPlayerByOpenID(open_id)
        if player then
            player:sendRawMessage(pack)
        else
            skynet.error("onForward2Client not find player open_id:" .. open_id .. " message_id:" .. data.message_id)
        end
    end

end
msg_center.setDefaultMessageHandler(MessageType.Forward2Client,onForward2Client)